/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package embeddedpaint.model.layers;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.util.Observable;


public abstract class ALayer extends Observable
{
    public static final int     G_MAX_ANGLE_DEGRES          = 360;
    public static final int     M_DEFAULT_IMAGE_TYPE        = BufferedImage.TYPE_INT_ARGB;
    public static final float   M_DEFAULT_OPACITY           = 1f;
    
    protected static final int  M_DEFAULT_POSITION_X        = 0;
    protected static final int  M_DEFAULT_POSITION_Y        = 0;
    
    private static final int    M_DEFAULT_ROTATION          = 0;
    private static final Color  M_DEFAULT_ICON_BORDER_COLOR = Color.BLACK;
    private static final int    M_DEFAULT_ICON_BORDER_SIZE  = 1;
    
    protected String            m_name;
    protected int               m_x;
    protected int               m_y;
    protected int               m_width;
    protected int               m_height;
    protected float             m_opacity;
    protected double            m_rotate;

    protected abstract void drawLayer(Graphics2D g2d);
    
    public ALayer (String m_name)
    {
        this.m_name     = m_name;
        
        this.m_y        = M_DEFAULT_POSITION_X;
        this.m_x        = M_DEFAULT_POSITION_Y;
        this.m_rotate   = M_DEFAULT_ROTATION;
        this.m_opacity  = M_DEFAULT_OPACITY;
    }

    public void move (int x, int y)
    {
        this.m_x += x;
        this.m_y += y;
        
        this.updateObservers();
    }

    @Override
    public String toString ()
    {
        return m_name;
    }

    public void updateObservers ()
    {
        this.setChanged();
        this.notifyObservers();
    }

    public void drawMe (Graphics2D g)
    {
        AffineTransform affineTransform = new AffineTransform();
        affineTransform.rotate(Math.toRadians(this.m_rotate), this.m_x, this.m_y);

        g.setTransform(affineTransform);
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, this.m_opacity));

        this.drawLayer(g);

        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC, M_DEFAULT_OPACITY));
        
        affineTransform.setToIdentity();
    }

    public Image getIconWithBorder (int width, int height)
    {
        BufferedImage icon = new BufferedImage(m_x + this.m_width, m_y + this.m_height, M_DEFAULT_IMAGE_TYPE);

        Graphics2D g2d = (Graphics2D) icon.getGraphics();
        
        this.drawMe(g2d);

        g2d.dispose();

        Image resizedIcon = new BufferedImage(width, height, M_DEFAULT_IMAGE_TYPE);

        g2d = (Graphics2D) resizedIcon.getGraphics();
        g2d.drawImage(icon, M_DEFAULT_POSITION_X, M_DEFAULT_POSITION_Y, width, height, m_x, m_y, m_x + this.m_width, m_y + this.m_height, null);
        g2d.setColor(M_DEFAULT_ICON_BORDER_COLOR);
        g2d.drawRect(M_DEFAULT_POSITION_X, M_DEFAULT_POSITION_Y, width - M_DEFAULT_ICON_BORDER_SIZE, height - M_DEFAULT_ICON_BORDER_SIZE);
        g2d.dispose();

        return resizedIcon;
    }

    public Image getIcon (int width, int height)
    {
        BufferedImage icon = new BufferedImage(m_x + this.m_width, m_y + this.m_height, M_DEFAULT_IMAGE_TYPE);

        Graphics2D g2d = (Graphics2D) icon.getGraphics();
        
        this.drawMe(g2d);

        g2d.dispose();

        Image resizedIcon = new BufferedImage(width, height, M_DEFAULT_IMAGE_TYPE);

        g2d = (Graphics2D) resizedIcon.getGraphics();
        g2d.drawImage(icon, M_DEFAULT_POSITION_X, M_DEFAULT_POSITION_Y, width, height, m_x, m_y, m_x + this.m_width, m_y + this.m_height, null);
        g2d.dispose();

        return resizedIcon;
    }

    public int getM_height ()
    {
        return m_height;
    }

    public String getM_name ()
    {
        return m_name;
    }

    public double getM_rotate ()
    {
        return m_rotate;
    }

    public int getM_width ()
    {
        return m_width;
    }

    public int getM_x ()
    {
        return m_x;
    }

    public int getM_y ()
    {
        return m_y;
    }
    
    public float getM_opacity ()
    {
        return m_opacity;
    }
    
    public void setM_height (int m_height)
    {
        this.m_height = m_height;
    }

    public void setM_name (String m_name)
    {
        this.m_name = m_name;
        
        this.updateObservers();
    }

    public void setM_rotate (double m_rotate)
    {
        this.m_rotate = m_rotate % G_MAX_ANGLE_DEGRES;
        
        this.updateObservers();
    }

    public void setM_width (int m_width)
    {
        this.m_width = m_width;
    }

    public void setM_x (int m_x)
    {
        this.m_x = m_x;
    }

    public void setM_y (int m_y)
    {
        this.m_y = m_y;
    }

    public void setM_opacity (float m_opacity)
    {
        this.m_opacity = m_opacity;
        
        this.updateObservers();
    }
}
